﻿using System;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Text.RegularExpressions;
using Evolution.Utilities;

namespace Evolution.UI.WebParts
{
    [Serializable]
    public abstract class BaseKeyValueAssertion : BaseAssertion
    {
        #region Fields

        private static string[] OperatorCaption = {
                                                   " is equal to ", 
                                                   " is not equal to ", 
                                                   " is greater than ", 
                                                   " is less than ", 
                                                   " is greater than or equal to ", 
                                                   " is less than or equal to ", 
                                                   " begins with ", 
                                                   " does not begin with ", 
                                                   " ends with ", 
                                                   " does not end with ", 
                                                   " contains ", 
                                                   " does not contain ", 
                                                   " match ", 
                                                   " does not match "
                                               };
        
        #endregion

        #region Properties

        public string Key { get; set; }

        public string Value { get; set; }

        public KeyValueOperators Operator { get; set; }

        #endregion

        #region Methods

        protected void InternalCreateInterface(string prefix, ControlCollectionBuilder builder, PageActionEditor editor, int index)
        {
            // Key
            TextBox key = new TextBox();
            key.ID = prefix + "Key" + index;
            key.CssClass = "UserInput";
            key.Style[HtmlTextWriterStyle.Width] = "175px";
            key.ToolTip = "Collection key";

            builder.AddTextBoxAndBuilder(key, false);

            builder.AddErrorPlaceholder(prefix + "CollectionsKey" + index);

            builder.AddStaticText("<br/><br/>");

            DropDownList list1 = new DropDownList();
            list1.ID = prefix + "Operator" + index;
            list1.Items.Add(new ListItem("is equal to", KeyValueOperators.IsEqualTo.ToString()));
            list1.Items.Add(new ListItem("is not equal to", KeyValueOperators.IsNotEqualTo.ToString()));
            list1.Items.Add(new ListItem("is greater than", KeyValueOperators.IsGreaterThan.ToString()));
            list1.Items.Add(new ListItem("is less than", KeyValueOperators.IsLessThan.ToString()));
            list1.Items.Add(new ListItem("is greater than or equal to", KeyValueOperators.IsGreaterThanOrEqualTo.ToString()));
            list1.Items.Add(new ListItem("is less than or equal to", KeyValueOperators.IsLessThanOrEqualTo.ToString()));
            list1.Items.Add(new ListItem("begins with", KeyValueOperators.BeginsWith.ToString()));
            list1.Items.Add(new ListItem("does not begin with", KeyValueOperators.DoesNotBeginWith.ToString()));
            list1.Items.Add(new ListItem("ends with", KeyValueOperators.EndsWith.ToString()));
            list1.Items.Add(new ListItem("does not end with", KeyValueOperators.DoesNotEndWith.ToString()));
            list1.Items.Add(new ListItem("contains", KeyValueOperators.Contains.ToString()));
            list1.Items.Add(new ListItem("does not contain", KeyValueOperators.DoesNotContain.ToString()));
            list1.Items.Add(new ListItem("match", KeyValueOperators.Match.ToString()));
            list1.Items.Add(new ListItem("does not match", KeyValueOperators.DoesNotMatch.ToString()));
            list1.Style[HtmlTextWriterStyle.Width] = "175px";

            builder.AddControl(list1);

            builder.AddStaticText("<br/><br/>");

            // Value
            TextBox value = new TextBox();
            value.ID = prefix + "Value" + index;
            value.CssClass = "UserInput";
            value.Style[HtmlTextWriterStyle.Width] = "175px";
            value.ToolTip = "Value to compare";

            builder.AddControl(value);
        }

        protected string InternalGetDescription(string subject)
        {
            return String.Format("{0} \"{1}\" {2} \"{3}\"", subject, this.Key, BaseKeyValueAssertion.OperatorCaption[(int)this.Operator], this.Value);
        }

        protected void InternalSyncChanges(string prefix, PageActionEditor editor, int index)
        {
            (editor.FindControl(prefix + "Key" + index) as TextBox).Text = this.Key;
            (editor.FindControl(prefix + "Operator" + index) as DropDownList).SelectedValue = this.Operator.ToString();
            (editor.FindControl(prefix + "Value" + index) as TextBox).Text = this.Value;
        }

        protected void InternalApplyChanges(string prefix, PageActionEditor editor, int index)
        {
            TextBox obj1 = editor.FindControl(prefix + "Key" + index) as TextBox;

            if (obj1.Text.Trim() == String.Empty)
                editor.RaiseError(prefix + "CollectionsKey" + index, "Specify a valid key in the collection.");

            this.Key = obj1.Text;
            this.Operator = (KeyValueOperators)Enum.Parse(typeof(KeyValueOperators), (editor.FindControl(prefix + "Operator" + index) as DropDownList).SelectedValue);
            this.Value = (editor.FindControl(prefix + "Value" + index) as TextBox).Text;
        }

        protected bool InternalEvaluate(string value, Page page, PageActionWebPart part)
        {
            switch (this.Operator)
            {
                case KeyValueOperators.BeginsWith:
                    return value.StartsWith(this.Value, StringComparison.InvariantCultureIgnoreCase);
                case KeyValueOperators.DoesNotBeginWith:
                    return !value.StartsWith(this.Value, StringComparison.InvariantCultureIgnoreCase);

                case KeyValueOperators.EndsWith:
                    return value.EndsWith(this.Value, StringComparison.InvariantCultureIgnoreCase);
                case KeyValueOperators.DoesNotEndWith:
                    return !value.EndsWith(this.Value, StringComparison.InvariantCultureIgnoreCase);

                case KeyValueOperators.IsEqualTo:
                    return value.Equals(this.Value, StringComparison.InvariantCultureIgnoreCase);
                case KeyValueOperators.IsNotEqualTo:
                    return !value.Equals(this.Value, StringComparison.InvariantCultureIgnoreCase);

                case KeyValueOperators.IsGreaterThan:
                    return value.CompareTo(value) > 0;
                case KeyValueOperators.IsGreaterThanOrEqualTo:
                    return value.CompareTo(value) >= 0;

                case KeyValueOperators.IsLessThan:
                    return value.CompareTo(value) < 0;
                case KeyValueOperators.IsLessThanOrEqualTo:
                    return value.CompareTo(value) <= 0;

                case KeyValueOperators.Match:
                case KeyValueOperators.DoesNotMatch:
                    Regex re = new Regex(this.Value);
                    return re.IsMatch(value) && this.Operator == KeyValueOperators.Match;

                case KeyValueOperators.Contains:
                    return value.Contains(value);
                default:    // case KeyValueOperators.DoesNotContain:                
                    return !value.Contains(value);
            }
        }

        public override bool IsValidAssertion(PageActionWebPart part, out string errorMessage)
        {
            errorMessage = String.Empty;
            if (StringUtility.IsNullOrEmpty(this.Key))
                errorMessage = "No key specified in the collection.";

            return String.IsNullOrEmpty(errorMessage);
        }

        #endregion
    }

    #region KeyValueOperators enum

    public enum KeyValueOperators
    {
        IsEqualTo = 0,
        IsNotEqualTo = 1,
        IsGreaterThan = 2,
        IsLessThan = 3,
        IsGreaterThanOrEqualTo = 4,
        IsLessThanOrEqualTo = 5,
        BeginsWith = 6,
        DoesNotBeginWith = 7,
        EndsWith = 8,
        DoesNotEndWith = 9,
        Contains = 10,
        DoesNotContain = 11,
        Match = 12,
        DoesNotMatch = 13
    }

    #endregion
}
